package org.cybzacg.convert.converters.date;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.exception.ConversionException;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 时间间隔转换器抽象基类
 * 为Duration和Period转换器提供通用逻辑
 *
 * @param <T> 时间间隔类型（Duration或Period）
 * @author cybzacg.blog
 * @version 4.0
 * @since 4.0
 */
@Slf4j
public abstract class AbstractIntervalConverter<T> extends AbstractTypeConverter {

    /**
     * 最大缓存大小，防止内存泄漏
     */
    private static final int MAX_CACHE_SIZE = 1000;

    /**
     * LRU缓存，自动淘汰最少使用的条目
     */
    protected final Map<String, T> cache = Collections.synchronizedMap(
            new LinkedHashMap<String, T>(MAX_CACHE_SIZE + 1, 0.75f, true) {
                @Override
                protected boolean removeEldestEntry(Map.Entry<String, T> eldest) {
                    boolean shouldRemove = size() > MAX_CACHE_SIZE;
                    if (shouldRemove) {
                        log.trace("缓存已满，移除最老条目: {}", eldest.getKey());
                    }
                    return shouldRemove;
                }
            });

    protected AbstractIntervalConverter(ConversionPriority priority) {
        super(priority);
        log.debug("{} 初始化完成", getClass().getSimpleName());
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <R> R doConvert(Object source, Class<R> targetType, R defaultValue, ConversionContext context)
            throws Exception {

        if (source == null) {
            return defaultValue != null ? defaultValue : (R) getDefaultValue();
        }

        // 如果已经是目标类型，直接返回
        if (targetType.isInstance(source)) {
            return (R) source;
        }

        try {
            T result = convertToInterval(source, context);
            if (result == null) {
                return defaultValue != null ? defaultValue : (R) getDefaultValue();
            }
            return (R) result;
        } catch (Exception e) {
            log.error("{}转换失败: {} -> {}", getIntervalTypeName(), source, targetType, e);
            throw new ConversionException(ConversionError.CONVERSION_FAILED,
                    getIntervalTypeName() + "转换失败: " + source + " -> " + targetType, e);
        }
    }

    /**
     * 将对象转换为时间间隔类型
     */
    protected T convertToInterval(Object source, ConversionContext context) throws ConversionException {
        if (source == null) {
            return null;
        }

        // 如果已经是目标类型，直接返回
        if (isIntervalType(source)) {
            return castToInterval(source);
        }

        // 字符串转换
        if (source instanceof String str) {
            return convertFromString(str, context);
        }

        // 数字转换
        if (source instanceof Number number) {
            return convertFromNumber(number, context);
        }

        throw new ConversionException(ConversionError.UNSUPPORTED_CONVERSION,
                "无法将类型 " + source.getClass().getSimpleName() + " 转换为" + getIntervalTypeName());
    }

    /**
     * 从字符串转换
     */
    protected T convertFromString(String source, ConversionContext context) throws ConversionException {
        String str = source.trim();
        if (str.isEmpty()) {
            return null;
        }

        // 尝试缓存
        T cached = cache.get(str);
        if (cached != null) {
            return cached;
        }

        // 尝试ISO-8601格式
        try {
            T result = parseIsoFormat(str);
            cache.put(str, result);
            return result;
        } catch (Exception e) {
            log.trace("ISO-8601格式解析失败，尝试其他格式: {}", e.getMessage());
        }

        // 尝试中文格式
        try {
            if (containsChineseUnits(str)) {
                T result = parseChineseFormat(str);
                cache.put(str, result);
                return result;
            }
        } catch (Exception e) {
            log.trace("中文格式解析失败，尝试其他格式: {}", e.getMessage());
        }

        // 尝试简单格式
        try {
            T result = parseSimpleFormat(str);
            if (result != null) {
                cache.put(str, result);
                return result;
            }
        } catch (Exception e) {
            log.trace("简单格式解析失败，尝试其他格式: {}", e.getMessage());
        }

        // 尝试纯数字
        try {
            T result = parseNumericString(str);
            cache.put(str, result);
            return result;
        } catch (NumberFormatException e) {
            log.trace("数字格式解析失败: {}", e.getMessage());
        }

        throw new ConversionException(ConversionError.FORMAT_ERROR,
                "无法将字符串 '" + str + "' 转换为" + getIntervalTypeName());
    }

    /**
     * 从数字转换
     */
    protected abstract T convertFromNumber(Number source, ConversionContext context);

    /**
     * 解析ISO-8601格式
     */
    protected abstract T parseIsoFormat(String str);

    /**
     * 解析中文格式
     */
    protected abstract T parseChineseFormat(String str);

    /**
     * 解析简单格式
     */
    protected abstract T parseSimpleFormat(String str);

    /**
     * 解析纯数字字符串
     */
    protected abstract T parseNumericString(String str);

    /**
     * 检查字符串是否包含中文单位
     */
    protected abstract boolean containsChineseUnits(String str);

    /**
     * 检查对象是否为目标时间间隔类型
     */
    protected abstract boolean isIntervalType(Object obj);

    /**
     * 强制转换为目标时间间隔类型
     */
    protected abstract T castToInterval(Object obj);

    /**
     * 获取默认值
     */
    protected abstract T getDefaultValue();

    /**
     * 获取时间间隔类型名称
     */
    protected abstract String getIntervalTypeName();

    /**
     * 从中文字符串中提取数字（通用辅助方法）
     */
    protected String extractChineseNumber(String str, String... units) {
        for (String unit : units) {
            int index = str.indexOf(unit);
            if (index != -1) {
                int start = index;
                while (start > 0 && (Character.isDigit(str.charAt(start - 1)) || str.charAt(start - 1) == '.')) {
                    start--;
                }
                return str.substring(start, index).trim();
            }
        }
        return "";
    }

    /**
     * 清除缓存
     */
    public void clearCache() {
        cache.clear();
    }

    /**
     * 获取缓存大小
     */
    public int getCacheSize() {
        return cache.size();
    }
}
